package com.example.lotterysystem.service.activitystatus.impl;

import com.example.lotterysystem.common.errorcode.ServiceErrorCodeConstants;
import com.example.lotterysystem.common.exception.ServiceException;
import com.example.lotterysystem.service.ActivityService;
import com.example.lotterysystem.service.activitystatus.ActivityStatusManager;
import com.example.lotterysystem.service.activitystatus.operater.AbstractActivityOperator;
import com.example.lotterysystem.service.dto.ConvertActivityStatusDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.PropertyResolver;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 活动状态管理实现类
 * 
 * 该类负责处理活动、奖品及用户状态的转换操作，通过依赖注入的方式获取各种状态操作器（AbstractActivityOperator），
 * 并按照预定义顺序执行状态转换逻辑。此类采用组件注解进行 Spring 管理，并支持事务控制。
 */
@Component
public class ActivityStatusManagerImpl implements ActivityStatusManager {
    private static final Logger logger = LoggerFactory.getLogger(ActivityStatusManagerImpl.class);

    /**
     * 存储所有 AbstractActivityOperator 实现类的映射表，用于状态转换处理
     */
    @Autowired
    private final Map<String, AbstractActivityOperator> operatorMap = new HashMap<>();

    /**
     * Spring 属性解析器，可用于读取配置属性
     */
    @Autowired
    private PropertyResolver propertyResolver;

    /**
     * 活动服务接口，用于缓存活动信息等操作
     */
    @Autowired
    private ActivityService activityService;
    private AbstractActivityOperator operator;


    /**
     * 执行活动状态扭转操作。
     *
     * 该方法根据传入的 DTO 参数判断需要转换的状态类型，并调用相应的处理器进行状态转换。
     * 转换完成后会更新活动缓存以保证数据一致性。
     *
     * @param convertActivityStatusDTO 状态转换所需的参数封装对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handlerEvent(ConvertActivityStatusDTO convertActivityStatusDTO) {
        // 日志提示：当前状态扭转存在维护性差和扩展性低的问题，建议后续重构优化
        if (CollectionUtils.isEmpty(operatorMap)) {
            logger.warn("operatorMap 为空！");
            return;
        }

        // 创建当前操作器副本以避免并发修改
        Map<String, AbstractActivityOperator> curMap = new HashMap<>(operatorMap);

        Boolean update = false;

        // 先处理人员、奖品状态转换（sequence=1）
        update = processConvertStatus(convertActivityStatusDTO, curMap, 1);

        // 后处理活动状态转换（sequence=2）
        update = processConvertStatus(convertActivityStatusDTO, curMap, 2) || update;

        // 如果有状态发生更新，则刷新缓存
        if (update) {
            activityService.cacheActivity(convertActivityStatusDTO.getActivityId());
        }
    }

    /**
     * 回滚处理活动状态事件。
     *
     * 此方法用于将活动及其相关资源的状态回滚到之前的状态。
     * 它会遍历operatorMap中的所有操作符，并对每个操作符执行转换逻辑。
     * 最后，更新活动的缓存以反映新的状态。
     *
     * @param convertActivityStatusDTO 包含转换所需数据的DTO对象
     */
    @Override
    public void rollbackHandlerEvent(ConvertActivityStatusDTO convertActivityStatusDTO) {
        // operatorMap : 活动、奖品、人员
        // 活动是否需要回滚？ 绝对需要
        // 原因：奖品状态都为INIT了，那么活动下的奖品绝对没有抽完
        for (AbstractActivityOperator operator : operatorMap.values()) {
            operator.convert(convertActivityStatusDTO);
        }

        // 缓存更新
        activityService.cacheActivity(convertActivityStatusDTO.getActivityId());
    }

    /**
     * 执行指定顺序的状态转换处理。 
     *
     * 遍历所有的 AbstractActivityOperator 实现类，筛选出满足条件的操作器并执行其转换逻辑。
     *
     * @param convertActivityStatusDTO 状态转换所需参数
     * @param curMap 当前可用操作器映射表
     * @param sequence 操作器执行顺序标识
     * @return 是否进行了状态更新
     */
    private Boolean processConvertStatus(ConvertActivityStatusDTO convertActivityStatusDTO,
                                         Map<String, AbstractActivityOperator> curMap,
                                         int sequence) {
        Boolean update = false;

        // 使用迭代器遍历操作器集合
        Iterator<Map.Entry<String, AbstractActivityOperator>> iterator = curMap.entrySet().iterator();
        while (iterator.hasNext()) {
            AbstractActivityOperator operator = iterator.next().getValue();

            // 判断是否需要转换以及是否匹配当前处理顺序
            if (operator.sequence() != sequence
                    || !operator.needConvert(convertActivityStatusDTO)) {
                continue;
            }

            // 执行转换逻辑
            if (!operator.convert(convertActivityStatusDTO)) {
                logger.error("{}状态转换失败！", operator.getClass().getName());
                throw new ServiceException(ServiceErrorCodeConstants.ACTIVITY_STATUS_CONVERT_ERROR);
            }

            // 移除已处理的操作器，防止重复执行
            iterator.remove();
            update = true;
        }

        return update;
    }
}
